package org.grow.secure.config;

import org.grow.secure.data.SecureProperties;
import org.grow.secure.exception.ExceptionBridge;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AnonymousAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextPersistenceFilter;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

import javax.servlet.Filter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.util.Arrays;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @Author: xwg
 * @CreateDate: 2022/5/30
 */

@EnableWebSecurity
@EnableRedisHttpSession
@EnableConfigurationProperties({SecureProperties.class})
@Import(ExceptionBridge.class)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private SecureProperties secureProperties;

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.cors().disable();
        http.csrf().disable();
        http.httpBasic().disable();
        http.formLogin().disable();
        http.logout().disable();

        if (secureProperties.getEnableAnonymous()) {
            http.anonymous();

        } else {
            http.anonymous().disable();
        }
        //        1 以下二者都不声明 ：则无任何拦截效果 不论身份认证 不论权限拦截
//        声明permitAll 效果是 身份认证必须有 无权限拦截
//        声明authenticated 效果是 既有身份认证，也有权限拦截
        http.authorizeRequests().anyRequest().permitAll();
//        http.authorizeRequests().anyRequest().authenticated();
        http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
            response.setStatus(401);
            response.getWriter().println("生产环境不允许无身份用户登录");
        });
        http.addFilterBefore((servletRequest, servletResponse, filterChain) -> {
            System.out.println("Debug: Cookie: ");
            HttpServletRequest req = (HttpServletRequest) servletRequest;
            HttpServletResponse res = (HttpServletResponse) servletResponse;
            Cookie[] cookies = req.getCookies();
            if (cookies != null) {
                for (Cookie cookie : cookies) {
                    System.out.println(cookie.getName()+" : cookie : "+cookie.getValue());
                }
            }
//            System.out.println("user:  "+SecurityContextHolder.getContext().getAuthentication().getName());
            System.out.println("user");
            if (SecurityContextHolder.getContext()!=null){
                System.out.println("auth : "+SecurityContextHolder.getContext().getAuthentication());
                if (SecurityContextHolder.getContext().getAuthentication()!=null){
                    String name = SecurityContextHolder.getContext().getAuthentication().getName();
                    System.out.println(" final :name "+name);
                }
            }
            filterChain.doFilter(servletRequest, servletResponse);
//            System.out.println("user:  "+SecurityContextHolder.getContext().getAuthentication().getName());
        }, AnonymousAuthenticationFilter.class);
    }

    @Bean
    public Point point() {
        return new Point(2, 3);
    }

    /**
     * config by ms-gateway module
     */
//    @Bean
    public FilterRegistrationBean<Filter> corsBean() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setMaxAge(3600l);
        corsConfiguration.addAllowedOriginPattern("*");
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.setAllowedMethods
                (Stream.of("POST", "GET", "DELETE", "PUT", "OPTIONS")
                        .collect(Collectors.toList()));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        CorsFilter corsFilter = new CorsFilter(source);
        FilterRegistrationBean<Filter> bean = new FilterRegistrationBean<>();
        bean.setFilter(corsFilter);
        bean.setOrder(-1000);
        return bean;
    }
}
